package cn.fintecher.pangolin.service.manage.service;

import cn.fintecher.pangolin.common.enums.BaseSelect;
import cn.fintecher.pangolin.common.enums.BaseStatus;
import cn.fintecher.pangolin.common.enums.ConfigState;
import cn.fintecher.pangolin.common.enums.ManagementType;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.BeanUtils;
import cn.fintecher.pangolin.common.utils.RepositoryUtil;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.PrincipalPayment;
import cn.fintecher.pangolin.entity.mysql.*;
import cn.fintecher.pangolin.service.manage.elastic.PrincipalPaymentElastic;
import cn.fintecher.pangolin.service.manage.repository.ContactConfigRepository;
import cn.fintecher.pangolin.service.manage.repository.PrincipalRepository;
import cn.fintecher.pangolin.service.manage.repository.StatusConfigRepository;
import cn.fintecher.pangolin.service.manage.request.AddPrincipalRequest;
import cn.fintecher.pangolin.service.manage.request.FindPrincipalRequest;
import cn.fintecher.pangolin.service.manage.request.ModifyPrincipalRequest;
import cn.fintecher.pangolin.service.manage.response.PrincipalResponse;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.IteratorUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.modelmapper.ModelMapper;
import org.modelmapper.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 10:26 2019/8/15
 */

@Service("principalService")
@Transactional(rollbackFor = Exception.class)
public class PrincipalService {
    @Autowired
    private BaseService baseService;

    @Autowired
    private PrincipalRepository principalRepository;

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private ContactConfigRepository contactConfigRepository;

    @Autowired
    private PrincipalPaymentElastic principalPaymentElastic;

    @Autowired
    private StatusConfigRepository statusConfigRepository;

    /**
     * 新增委托方
     */
    @Transactional
    public void addPrincipal(AddPrincipalRequest request, String token) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(QPrincipal.principal.name.eq(request.getName()));
        boolean exists = principalRepository.exists(booleanBuilder);
        if (exists) {
            throw new BadRequestException(null, "", "principal.is.exists");
        }
        UserModel userModel = baseService.getUserByToken(token);
        Principal principal = new Principal();
        BeanUtils.copyPropertiesIgnoreNull(request, principal);
        principal.setStatus(BaseStatus.ON);
        principal.process(userModel.getId(), ZWDateUtil.getNowDateTime(), true);
        Principal savePrincipal = principalRepository.save(principal);
        //生成催记项配置
        generalConfigResult(savePrincipal);
        //生成案件状态
        generateStatusConfig(savePrincipal);
    }

    /***
     * 生成联络结果
     * @param principal
     */
    public void generalConfigResult(Principal principal) {
        Iterable<ContactConfig> all = contactConfigRepository.findAll(QContactConfig.contactConfig.level.eq(0));
        List<ContactConfig> levelThreeList = new ArrayList<>();
        if (all.iterator().hasNext()) {
            ContactConfig contactResult = all.iterator().next();
            ContactConfig contactResultNew = new ContactConfig();
            contactResultNew.setParent(contactResult.getId());
            contactResultNew.setLevel(contactResult.getLevel() + 1);
            contactResultNew.setPrincipalId(principal.getId());
            contactResultNew.setPrincipalName(principal.getName());
            contactResultNew.setIsExtension(BaseSelect.YES);
            contactResultNew.setName(principal.getName());
            contactResultNew.setSort(0);
            contactResultNew.setIsInitData(BaseSelect.NO);
            contactResultNew = contactConfigRepository.save(contactResultNew);
            List<ContactConfig> initData = Lists.newArrayList(contactConfigRepository.findAll(QContactConfig.contactConfig.isInitData.eq(BaseSelect.YES)));
            if (initData.size() > 0) {
                List<ContactConfig> levelTwo = initData.stream().filter(x -> Objects.equals(x.getLevel(), 2)).collect(Collectors.toList());
                if (levelTwo.size() > 0) {
                    for (ContactConfig levelTwoConfig : levelTwo) {
                        ContactConfig newLevelTwo = new ContactConfig();
                        BeanUtils.copyProperties(levelTwoConfig, newLevelTwo);
                        newLevelTwo.setId(null);
                        newLevelTwo.setIsInitData(BaseSelect.NO);
                        newLevelTwo.setParent(contactResultNew.getId());
                        newLevelTwo.setPrincipalName(principal.getName());
                        newLevelTwo.setHideList(null);
                        newLevelTwo.setPrincipalId(principal.getId());
                        ContactConfig contactConfig = contactConfigRepository.save(newLevelTwo);
                        List<ContactConfig> levelThree = initData.stream().filter(x -> Objects.equals(x.getLevel(), 3) && Objects.equals(x.getParent(), levelTwoConfig.getId())).collect(Collectors.toList());
                        if (levelThree.size() > 0) {
                            for (ContactConfig levelThreeConfig : levelThree) {
                                ContactConfig newLevelThreeConfig = new ContactConfig();
                                BeanUtils.copyProperties(levelThreeConfig, newLevelThreeConfig);
                                newLevelThreeConfig.setId(null);
                                newLevelThreeConfig.setIsInitData(BaseSelect.NO);
                                newLevelThreeConfig.setParent(contactConfig.getId());
                                newLevelThreeConfig.setPrincipalName(principal.getName());
                                newLevelThreeConfig.setHideList(null);
                                newLevelThreeConfig.setPrincipalId(principal.getId());
                                levelThreeList.add(newLevelThreeConfig);
                            }
                        }
                    }
                }
            }
            if (levelThreeList.size() > 0) {
                contactConfigRepository.saveAll(levelThreeList);
            }
        }
    }

    /**
     * 修改委托方
     */
    public void modifyPrincipal(ModifyPrincipalRequest request, String token) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(QPrincipal.principal.name.eq(request.getName())).and(QPrincipal.principal.id.ne(request.getId()));
        boolean exists = principalRepository.exists(booleanBuilder);
        if (exists) {
            throw new BadRequestException(null, "", "principal.is.exists");
        }
        UserModel userModel = baseService.getUserByToken(token);
        Principal principal = principalRepository.findById(request.getId()).orElseThrow(() -> new BadRequestException(null, "principal", "principal.is.null"));
        BeanUtils.copyPropertiesIgnoreNull(request, principal);
        principal.process(userModel.getId(), ZWDateUtil.getNowDateTime(), false);
        principalRepository.save(principal);
        //处理委托方报表模型
        if (request.getStatus().equals(BaseStatus.OFF)) {
            BoolQueryBuilder builder = new BoolQueryBuilder();
            builder.must(QueryBuilders.matchPhraseQuery("principalId.keyword", request.getId()));
            Iterable<PrincipalPayment> iterable = principalPaymentElastic.search(builder);
            List<PrincipalPayment> list = IterableUtils.toList(iterable);
            for (PrincipalPayment principalPayment : list) {
                principalPayment.setIsStatistics(BaseSelect.NO);
            }
            RepositoryUtil.saveData(principalPaymentElastic, list);
        }
    }

    /**
     * 多条件查询委托方
     */
    public Page<PrincipalResponse> findAllPrincipal(FindPrincipalRequest request, Pageable pageable, String token) {
        UserModel userModel = baseService.getUserByToken(token);
        BooleanBuilder builder = request.getBuilder();
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            builder.and(QPrincipal.principal.id.in(userModel.getPrincipalIds()));
        }
        Sort sort = new Sort(Sort.Direction.DESC, "operateTime");
        pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        Page<Principal> page = principalRepository.findAll(builder, pageable);
        return page.map(e -> modelMapper.map(e, PrincipalResponse.class));
    }

    /**
     * 查询全部委托方
     */
    public List<PrincipalResponse> findAllPrincipalNoPage(String token) {
        UserModel userModel = baseService.getUserByToken(token);
        BooleanBuilder builder = new BooleanBuilder();
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            builder.and(QPrincipal.principal.id.in(userModel.getPrincipalIds()));
        }
        builder.and(QPrincipal.principal.status.eq(BaseStatus.ON));
        Iterable<Principal> iterable = principalRepository.findAll(builder);
        Type listType = new TypeToken<List<PrincipalResponse>>() {
        }.getType();
        return modelMapper.map(IterableUtils.toList(iterable), listType);
    }

    /**
     * 生成案件状态
     */
    private void generateStatusConfig(Principal principal) {
        Iterable<StatusConfig> iterable = statusConfigRepository.findAll(QStatusConfig.statusConfig.principalId.isNull());
        List<StatusConfig> list = IterableUtils.toList(iterable);
        if (!list.isEmpty()) {
            List<StatusConfig> statusConfigs = new ArrayList<>();
            for (StatusConfig statusConfig : list) {
                StatusConfig config = new StatusConfig();
                BeanUtils.copyPropertiesIgnoreNull(statusConfig, config);
                config.setId(null);
                config.setPrincipalId(principal.getId());
                config.setPrincipalName(principal.getName());
                statusConfigs.add(config);
            }
            RepositoryUtil.saveData(statusConfigRepository, statusConfigs);
        }
    }
}
